package com.warm.common.excel;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Date: 2019/11/15 13:36
 * @Author: LChuang
 * @Description:
 */
public class Tree {

    private Node root;

    public Tree(){
        //创建一个name为空的树
        this.root = new Node(-1);
    }

    /**
     * 为节点增加子节点
     * @param titles
     */
    public void add(Node node, String... titles){
        for(int i=0; i < titles.length; i++){
            Node childNode = new Node(node.getLevel()+1, node.getName(), titles[i]);
            node.getChild().add(childNode);
        }
    }

    public void add(String... titles){
        this.add(this.root, titles);
    }

    /**
     * 获取所有节点 --> 包括自己
     * @param node
     * @param nodes
     * @return
     */
    public List<Node> getAllChild(Node node, List<Node> nodes){
        if(!node.getChild().isEmpty()){
            nodes.addAll(node.getChild());
            for(Node item : node.getChild()){
                getAllChild(item, nodes);
            }
        }
        return nodes;
    }

    /**
     * 获取整个数的节点
     * @return
     */
    public List<Node> getAllNodes(){
        List<Node> list = new ArrayList<>();
        list.add(this.root);
        return this.getAllChild(this.root, list);
    }

    public List<Node> getAllChild(){
        List<Node> list = new ArrayList<>();
        return this.getAllChild(this.root, list);
    }

    public List<Node> getAllChild(Node node){
        List<Node> list = new ArrayList<>();
        return this.getAllChild(node, list);
    }

    public List<Node> getLevelNodes(Integer level){
        List<Node> list = getAllNodes();
        return list.stream().filter(node -> node.getLevel() == level).collect(Collectors.toList());
    }

    public Node getNode(String parentName, String name){
        if(parentName == null){
            if(name == null){
                return this.root;
            }else {
                Optional<Node> node = this.root.getChild().stream().filter(item -> item.getName().equals(name)).findAny();
                if(node.isPresent()){
                    return node.get();
                }
                return null;
            }
        }
        Optional<Node> node = this.getAllChild().stream().filter(item -> parentName.equals(item.getParentName()) && name.equals(item.getName())).findAny();
        if(node.isPresent()){
            return node.get();
        }
        return null;
    }

    public Node getParent(Node node){
        if(node.getParentName() == null){
            return null;
        }
        return this.getAllNodes().stream().filter(item -> item.getLevel() == node.getLevel()-1 && node.getParentName().equals(item.getName())).findAny().get();
    }

    public List<Node> getLeafs(Node node, List<Node> leafs){
        if(node.getChild().isEmpty()){
            leafs.add(node);
        }else {
            for(Node item : node.getChild()){
                getLeafs(item, leafs);
            }
        }
        return leafs;
    }

    public List<Node> getLeafs(){
        List<Node> leafs = new ArrayList<>();
        return this.getLeafs(this.root, leafs);
    }

    public Integer getLevel(){
        return this.getAllChild().stream().max(Comparator.comparing(Node::getLevel)).get().getLevel();
    }

    public Integer getLevel(Node node){
        return this.getAllChild(node).stream().max(Comparator.comparing(Node::getLevel)).get().getLevel();
    }

    public Integer getWidth(){
        return this.getLeafs().size();
    }
}
